Skip to content

fix(linker): escape metadata strings and emit @defer block dependencies - #618

Open
GabeSilvaDev wants to merge 1 commit into
voidzero-dev:mainfrom
GabeSilvaDev:fix/linker-escape-defer
Open

GabeSilvaDev wants to merge 1 commit into
voidzero-dev:mainfrom
GabeSilvaDev:fix/linker-escape-defer

Conversation

@GabeSilvaDev

Copy link
Copy Markdown
Contributor

Summary

Two linker bugs that change the code it emits for partial declarations.

Strings written without escaping

Several metadata strings were put between quotes as they came:

  • pipe name
  • host.classAttribute (each class)
  • controlCreate.passThroughInput
  • attribute values in selector
  • quoted inputs keys ("a.b")

A quote, backslash or newline in any of them broke the output, or turned part of the string into code:

// input
i0.ɵɵngDeclarePipe({ ..., name: 'a"+x+"' })
// before
i0.ɵɵdefinePipe({ name: "a"+x+"", type: P, pure: true })
// after
i0.ɵɵdefinePipe({ name: "a\"+x+\"", type: P, pure: true })

They now go through escape_string, like the other strings the linker already emits (host.attributes, styleAttribute).

deferBlockDependencies ignored

The linker never read deferBlockDependencies, so a linked @defer block got no dependency function (ɵɵdefer(1, 0)) and its lazy import() was dropped. A library that uses @defer with lazy dependencies rendered the deferred component as an unknown element.

Each entry is now matched to its @defer block in the order the binder lists them (getDeferBlocks()), as createR3ComponentDeferMetadata does in the TS linker. A null entry, or a block past the end of the list, gets no dependency function. The functions go through IngestOptions::defer_blocks into the existing PerBlock path and are emitted as written.

// input
template: "@defer { <lazy-cmp/> }",
deferBlockDependencies: [() => [import("./lazy").then(m => m.LazyCmp)]]
// before
i0.ɵɵdefer(1, 0);
// after
const C_Defer_1_DepsFn = () => [import("./lazy").then(m => m.LazyCmp)];
i0.ɵɵdefer(1, 0, C_Defer_1_DepsFn);

Tests

  • test_link_escapes_metadata_strings: each of the five fields above with a quote in it, including passThroughInput (ɵɵControlFeature("f\"+x+\"")).
  • test_link_defer_block_dependencies: nested blocks, a block inside @placeholder and a null entry. The expected fragments are the Angular linker's output for the same input (@angular/compiler-cli 22.2.3 Babel plugin, @angular/compiler 22.2.2).
  • cargo test --all-features passes, and conformance is 1264/1264 with no snapshot change.

Pipe names, host class attributes, ControlFeature inputs, selector values and quoted input keys were written between quotes as is, so a quote, backslash or newline in them broke or changed the emitted code.

deferBlockDependencies was never read, so linked @defer blocks had no dependency function and their lazy imports were dropped. Each entry is now matched to its block in the binder's order, as the TS linker does.
Copilot AI balanced review requested due to automatic review settings October 23, 2026 00:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing. Review the Copilot code review billing settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-23T00:20:54.887604Z 8d7eb5e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants